//
//  JKImageBrowserView.swift
//  ZhiHuDaily-Swift
//
//  Created by albert on 2018/3/9.
//  Copyright © 2018年 安永博. All rights reserved.
//

import UIKit
import AssetsLibrary
import Kingfisher
import JKAlertX

class JKImageBrowserView: UIView {
    
    
    
    /** 根据image显示图片 */
    public class func showWith(image: UIImage?) {
        
        guard let _ = image else { return }
        
        let vv = JKImageBrowserView()
        
        vv.image = image
        
        UIApplication.shared.delegate?.window!?.rootViewController?.view.addSubview(vv)
    }
    
    /** 根据imageUrlStr显示图片 */
    public class func showWith(imageUrlStr: String?) {
        
        guard let _ = imageUrlStr else { return }
        
        let vv = JKImageBrowserView()
        
        vv.imageUrlStr = imageUrlStr
        
        UIApplication.shared.delegate?.window!?.rootViewController?.view.addSubview(vv)
    }
    
    // MARK: - 私有属性
    
    private var skinModel: String {
        
        return UserDefaults.standard.string(forKey: JKCurrentSkinModelKey) ?? JKDaySkinModelValue
    }
    
    private let bgAlpha: CGFloat = 0.7
    private let animationDuration: CGFloat = 0.5
    
    private var isGonnaDismiss = false
    
    /** 图片 */
    private var image: UIImage? {
        
        didSet{
            
            if image == nil {
                return
            }
            
            indicatorView.stopAnimating()
            saveButton.isHidden = false
            
            let scale = image!.size.width / image!.size.height
            let imageWidth = JKScreenW
            let imageHeight = imageWidth / scale
            
            // 2.设置图片frame
            if self.imageUrlStr == nil {
                
                self.imageView.image = image
            }
            self.imageView.frame = CGRect(x: 0, y: 0, width: imageWidth, height: imageHeight)
            
            // 3.计算顶部和底部内边距
            let offsetY = (JKScreenH - imageHeight) * 0.5
            
            // 4.设置图片位置
            if (imageHeight > JKScreenH) { // 计算后的图片高度 > 屏幕高度
                
                // 设置contentSize，让长图可以滚动
                scrollView.contentSize = CGSize(width: imageWidth, height: imageHeight)
                
                // 长图滚到底部翻页后再回来，让它自动回到顶部
                //self.scrollView.contentOffset = CGPointZero
                
            }else { // 计算后的图片高度 <= 屏幕高度
                
                // 居中显示使用contentInset，注意底部也要写上，否则可能会出现位置偏移的问题
                scrollView.contentInset = UIEdgeInsetsMake(offsetY, 0, offsetY, 0)
            }
            
            self.coverView.frame = self.imageView.bounds
            
            self.imageView.transform = CGAffineTransform(scaleX: 0.1, y: 0.1)
            
            UIView.animate(withDuration: TimeInterval(animationDuration), animations: {
                
                self.imageView.transform = CGAffineTransform.identity
                self.imageView.alpha = 1
                self.coverView.alpha = 1
                
            }) { (_) in
                
                self.showImageFinished = true
            }
        }
    }
    
    /** 图片url */
    private var imageUrlStr: String? {
        
        didSet{
            
            if imageUrlStr == nil {
                return
            }
            
            if let url = URL(string: imageUrlStr!) {
                
                weak var weakSelf = self
                
                imageView.kf.setImage(with: url, placeholder: nil, options: nil, progressBlock: nil, completionHandler: { (image, error, cacheType, url) in
                    
                    if error != nil {
                        
                        JKProgressHUD.showError(withStatus: "加载图片失败！")
                        
                        weakSelf?.selfDismiss()
                        
                        return
                    }
                    
                    weakSelf?.image = image
                })
            }
        }
    }
    
    /** imageView */
    private lazy var imageView: UIImageView = {
        
        let imageView = UIImageView()
        
        scrollView.addSubview(imageView)
        imageView.alpha = 0
        imageView.isUserInteractionEnabled = true
        imageView.addGestureRecognizer(UILongPressGestureRecognizer(target: self, action: #selector(imageLongPress(gesture:))))
        
        return imageView
    }()
    
    /** scrollView */
    private lazy var scrollView: UIScrollView = {
        
        let scrollView = UIScrollView(frame: JKScreenBounds)
        
        scrollView.jk_adapt_iOS_11_scrollView()
        insertSubview(scrollView, at: 0)
        
        scrollView.delegate = self
        
        scrollView.minimumZoomScale = 1
        scrollView.maximumZoomScale = 2
        
        scrollView.showsHorizontalScrollIndicator = false
        scrollView.showsVerticalScrollIndicator = false
        
        scrollView.alwaysBounceVertical = true
        scrollView.alwaysBounceHorizontal = true
        
        return scrollView
    }()
    
    /** 保存按钮 */
    private lazy var saveButton: UIButton = {
        
        let saveButton = UIButton(type: UIButtonType.custom)
        
        saveButton.frame = CGRect(x: JKScreenW - 10 - 50, y: JKScreenH - 50 - JKCurrentHomeIndicatorHeight, width: 50, height: 50)
        saveButton.isHidden = true
        saveButton.setImage(UIImage(named: "Menu_Download"), for: UIControlState.normal)
        saveButton.addTarget(self, action: #selector(saveButtonClick), for: UIControlEvents.touchUpInside)
        addSubview(saveButton)
        
        return saveButton
    }()
    
    /** 旋转菊花 */
    private lazy var indicatorView: UIActivityIndicatorView = {
        
        let indicatorView = UIActivityIndicatorView(activityIndicatorStyle: UIActivityIndicatorViewStyle.whiteLarge)
        indicatorView.center = center
        addSubview(indicatorView)
        
        return indicatorView
    }()

    
    /** 夜间模式遮盖view */
    private lazy var coverView: UIView = {
        
        let coverView = UIView()
        
        coverView.backgroundColor = UIColor.black.withAlphaComponent(bgAlpha)
        coverView.isUserInteractionEnabled = false
        coverView.isHidden = true
        imageView.addSubview(coverView)
        
        return coverView
        
    }()
    
    /** 当前的ZoomScale */
    private var currentZoomScale: CGFloat = 1
    
    /** 是否双击 */
    private var isDoubleTap: Bool = false
    
    /** 是否正在缩放 */
    private var isZooming: Bool = false
    
    /** 图片显示动画完毕 */
    private var showImageFinished: Bool = false
    
    // MARK: - 初始化
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        
        initialization()
    }
    
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        
        initialization()
    }
    
    private func initialization() {
        
        NotificationCenter.default.addObserver(self, selector: #selector(updateSkin), name: NSNotification.Name(rawValue: JKSkinModelDidChangedNotification), object: nil)

        scrollView.backgroundColor = UIColor.clear
        backgroundColor = UIColor.black.withAlphaComponent(0)
        indicatorView.startAnimating()
        
        let singleTap = UITapGestureRecognizer(target: self, action: #selector(selfDismiss))
        addGestureRecognizer(singleTap)

        let doubleTap = UITapGestureRecognizer(target: self, action: #selector(doubleTap(tap:)))
        doubleTap.numberOfTapsRequired = 2
        addGestureRecognizer(doubleTap)

        singleTap.require(toFail: doubleTap)

        UIApplication.shared.setStatusBarHidden(true, with: UIStatusBarAnimation.fade)
    }
    
    @objc private func doubleTap(tap: UITapGestureRecognizer) {
        
        isDoubleTap = true
        
        let touchPoint = tap.location(in: imageView)
        
        let point = imageView.convert(touchPoint, from: imageView)
        
        if imageView.point(inside: point, with: nil) {
            return
        }
        
        // 双击缩小
        if (imageView.frame.size.width > JKScreenW) {
            
            scrollView.setZoomScale(1, animated: true)
            
            return
        }
        
        // 双击放大
        scrollView.zoom(to: CGRect(x: touchPoint.x - 5, y: touchPoint.y - 5, width: 10, height: 10), animated: true)
    }
    
    /** 长按图片 */
    @objc private func imageLongPress(gesture: UILongPressGestureRecognizer) {
        
        if gesture.state == UIGestureRecognizerState.began {
            
            let _ = JKAlertView(title: nil, message: nil, style: JKAlertStyleActionSheet).addAction(JKAlertAction(title: "保存图片", style: JKAlertActionStyleDefault, handler: { (action) in
                
                self.saveButtonClick()
                
            }))?.show()
        }
    }
    
    /** 保存图片 */
    @objc private func saveButtonClick() {
        
        // 没下载完时不允许保存
        if imageView.image == nil {
            
            JKProgressHUD.showError(withStatus: "图片尚未加载完毕！")
            
            return
        }
        
        JKProgressHUD.showWithStatus(status: "正在保存图片...", isAllowUserAction: false)
        
        //将图片保存到相册
        //    UIImageWriteToSavedPhotosAlbum(self.pictureImageView.image, self, @selector(image:didFinishSavingWithError:contextInfo:), nil)
        //
        //    [PHAssetChangeRequest creationRequestForAssetFromImage:self.pictureImageView.image]
        
        DispatchQueue.global().async {
            
            // 通过url加载的图片
            if let _ = self.imageUrlStr {
                
                // 获取缓存路径
                let path = KingfisherManager.shared.cache.cachePath(forKey: self.imageUrlStr!)
                
                var url: URL? = nil
                
                // 判断文件是否存在 存在则直接保存，否则从网络加载
                if FileManager.default.fileExists(atPath: path) {
                    
                    url = URL(fileURLWithPath: path)
                    
                }else {
                    
                    url = URL(string: self.imageUrlStr!)
                }
                
                guard let imgUrl = url else {
                    
                    DispatchQueue.main.async {
                        
                        JKProgressHUD.showError(withStatus: "保存图片失败！")
                    }
                    return
                }
                
                guard let data = try? Data(contentsOf: imgUrl) else {
                    
                    DispatchQueue.main.async {
                        
                        JKProgressHUD.showError(withStatus: "保存图片失败！")
                    }
                    return
                }
                
                // 保存图片
                ALAssetsLibrary().writeImageData(toSavedPhotosAlbum: data, metadata: nil, completionBlock: { (url, err) in
                    
                    DispatchQueue.main.async {
                        
                        if err != nil {
                            
                            JKProgressHUD.showError(withStatus: "保存图片失败！")
                            
                        }else{
                            
                            JKProgressHUD.showSuccess(withStatus: "保存图片成功！")
                        }
                    }
                })
                
                return
            }
            
            // 通过直接展示UIImagede就直接保存
            if let _ = self.image {
                
                ALAssetsLibrary().writeImage(toSavedPhotosAlbum: self.image!.cgImage, metadata: nil, completionBlock: { (url, err) in
                    
                    DispatchQueue.main.async {
                        
                        if err != nil {
                            
                            JKProgressHUD.showError(withStatus: "保存图片失败！")
                            
                        }else{
                            
                            JKProgressHUD.showSuccess(withStatus: "保存图片成功！")
                        }
                    }
                })
                
                return
            }
        }
    }
    
    /** 单击退出 */
    @objc private func selfDismiss() {
        
        if self.image == nil {
            
            normalDismiss()
            
            return
        }
        imageView.image = nil
//        imageView.image = self.image
        imageView.layer.contents = self.image?.cgImage as Any?
        
        // 将self.imageView的坐标系转为self的坐标系
        let imageFrame = scrollView.convert(imageView.frame, to: self)
        
        // 创建要截取的imageView，截取显示在屏幕范围内的self.imageView
        let coverImgView = UIImageView()
        coverImgView.contentMode = UIViewContentMode.scaleAspectFit
        let X = imageFrame.origin.x > 0 ? imageFrame.origin.x : 0
        let Y = imageFrame.origin.y > 0 ? imageFrame.origin.y : 0
        
        let maxW = imageFrame.maxX > JKScreenW ? JKScreenW : imageFrame.maxX
        let maxH = imageFrame.maxY > JKScreenH ? JKScreenH : imageFrame.maxY
        
        let width = maxW - X
        let height = maxH - Y
        
//        coverImgView.backgroundColor = UIColor.red
        coverImgView.frame = CGRect(x: X, y: Y, width: width, height: height)
        addSubview(coverImgView)
        
        // 截取的范围 即coverImgView转换成self.imageView坐标系后的frame
        guard let clipRect = coverImgView.superview?.convert(coverImgView.frame, to: imageView) else {
            
            normalDismiss()
            
            return
        }
        
        //        // 计算原图片与coverImgView尺寸的比例
        //        let scaleW = (self.image!.size.width) / (imageView.frame.width)
        //        let scaleH = (self.image!.size.height) / (imageView.frame.height)
        //
        //        clipRect.size.width = clipRect.size.width * scaleW
        //        clipRect.size.height = clipRect.size.height * scaleH
        //
        //        clipRect.origin.x = self.image!.size.width - clipRect.size.width//clipRect.origin.x * scaleW
        //        clipRect.origin.y = self.image!.size.height - clipRect.size.height//clipRect.origin.y * scaleH
        //
        // 截取图片
        //    CGImageRef imageRef = CGImageCreateWithImageInRect([self.image CGImage], CGRectMake(clipRect.origin.x * scaleW, clipRect.origin.y * scaleH, clipRect.size.width * scaleW, clipRect.size.height * scaleH))
        
        UIGraphicsBeginImageContext(imageView.bounds.size)
        
        let context = UIGraphicsGetCurrentContext()
        
//        context?.ctm.rotated(by: CGFloat.pi)
//        context?.ctm.scaledBy(x: -1, y: 1)
//        context?.ctm.translatedBy(x: 0, y: -self.image!.size.height)
        
        imageView.layer.render(in: context!)
//        context?.draw(self.image!.cgImage!, in: imageView.bounds)
        let image = UIGraphicsGetImageFromCurrentImageContext()
        
        UIGraphicsEndImageContext()
        
        // 截取图片
        let imageRef = image?.cgImage?.cropping(to: clipRect)//WithImageInRect//CGImage()//CGImageCreateWithImageInRect([image CGImage], clipRect)
        
        let clipImage = UIImage(cgImage: imageRef!)
        
        coverImgView.image = clipImage
        
        imageView.removeFromSuperview()
        
        UIView.animate(withDuration: TimeInterval(animationDuration), animations: {
            
            self.backgroundColor = UIColor.black.withAlphaComponent(0)
            coverImgView.alpha = 0
            coverImgView.transform = CGAffineTransform(scaleX: 0.6, y: 0.6)
            self.saveButton.alpha = 0
            
        }) { (_) in
            
            self.removeFromSuperview()
        }
    }
    
    private func normalDismiss() {
        
        UIView.animate(withDuration: TimeInterval(animationDuration), animations: {
            
            self.indicatorView.stopAnimating()
            self.backgroundColor = UIColor.black.withAlphaComponent(0)
            self.saveButton.alpha = 0
            
        }) { (_) in
            
            self.removeFromSuperview()
        }
    }
    
    override func didMoveToSuperview() {
        super.didMoveToSuperview()
        
        if superview == nil {
            return
        }
        
        updateSkin()
        
        UIView.animate(withDuration: 0.25, animations: {
            
            self.backgroundColor = UIColor.black.withAlphaComponent(self.bgAlpha)
            
        })
    }
    
    override var frame: CGRect {
        
        didSet{
            
            super.frame = UIScreen.main.bounds
        }
    }
    
    deinit {
        
        NotificationCenter.default.removeObserver(self)
        
        UIApplication.shared.setStatusBarHidden(false, with: UIStatusBarAnimation.fade)
//        NotificationCenter.default.removeObserver(self)
    }
}


// MARK: - scrollView代理

extension JKImageBrowserView: UIScrollViewDelegate {
    
    func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
        
        isDoubleTap = false
    }
    
    func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
        
        if (scrollView.contentOffset.y < -80 - scrollView.contentInset.top) {
            
            isGonnaDismiss = true
            scrollView.bounces = false
            selfDismiss()
        }
    }
    
    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        
        if (scrollView.contentOffset.y + scrollView.contentInset.top >= 0) {
            return
        }
        
        if (self.isZooming || isGonnaDismiss || self.isDoubleTap) {
            return
        }
        
        var zoomScale = self.currentZoomScale - (scrollView.contentOffset.y + scrollView.contentInset.top) / (-80 - scrollView.contentInset.top) * 0.7
        zoomScale = zoomScale < 0.2 ? 0.2 : zoomScale
        imageView.transform = CGAffineTransform(scaleX: zoomScale, y: zoomScale)
        
        if (!showImageFinished) {
            return
        }
        
        self.backgroundColor = UIColor.black.withAlphaComponent(bgAlpha - (scrollView.contentOffset.y + scrollView.contentInset.top) / (-80 - scrollView.contentInset.top))
    }
    
    func viewForZooming(in scrollView: UIScrollView) -> UIView? {
        
        return imageView
    }
    
    func scrollViewWillBeginZooming(_ scrollView: UIScrollView, with view: UIView?) {
        
        isZooming = true
    }
    
    func scrollViewDidEndZooming(_ scrollView: UIScrollView, with view: UIView?, atScale scale: CGFloat) {
        
        currentZoomScale = scale
        isZooming = false
    }
    
    // 在缩放过程中不断调整位置，使用contentInset
    func scrollViewDidZoom(_ scrollView: UIScrollView) {
        
        //JKLog(imageView.bounds) // 从头至尾没有变化
        //JKLog(imageView.frame)  // 相当于contentSize
        //JKLog(scrollview.contentSize)
        
        // 计算内边距，注意只能使用frame
        var offsetX = (JKScreenW - imageView.frame.width) * 0.5
        var offsetY = (JKScreenH - imageView.frame.height) * 0.5
        
        // 当小于0的时候，放大的图片将无法滚动，因为内边距为负数时限制了它可以滚动的范围
        offsetX = (offsetX < 0) ? 0 : offsetX
        offsetY = (offsetY < 0) ? 0 : offsetY
        self.scrollView.contentInset = UIEdgeInsetsMake(offsetY, offsetX, offsetY, offsetX)
    }
    
    
}


extension JKImageBrowserView: JKUpdateSkinProtocol {
    
    func updateSkin() {
        
        coverView.isHidden = (skinModel == JKDaySkinModelValue)
    }
}
